#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <string>
#include <unistd.h>
#include <pthread.h>
#include <memory>
#include "Thread.hpp"

// 共享资源， 火车票
int tickets = 10000;

// 1. 多个执行流进行安全访问的共享资源 - 临界资源
// 2. 我们把多个执行流中，访问临界资源的代码 -- 临界区 -- 往往是线程代码的很小的一部分
// 3. 想让多个线程串行访问共享资源 -- 互斥
// 4. 对一个资源进行访问的时候，要么不做，要么做完 -- 原子性 ， 不是原子性的情况 -- 一个对资源进行的操作，如果只用一条汇编就能完成 -- 原子性
// 反之：不是原子的 -- 当前理解，方便表述

// 提出解决方案：加锁！

// 就需要尽可能的让多个线程交叉执行
// 多个线程交叉执行本质：就是让调度器尽可能的频繁发生线程调度与切换
// 线程一般在什么时候发生切换呢？时间片到了，来了更高优先级的线程，线程等待的时候。
// 线程是在什么时候检测上面的问题呢？从内核态返回用户态的时候，线程要对调度状态进行检测，如果可以，就直接发生线程切换

void *getTicket(void *args)
{
    // other code
    std::string username = static_cast<const char *>(args);
    // ThreadData *td = static_cast<ThreadData *>(args);
    while (true)
    {
        // 加锁和解锁的过程多个线程串行执行的，程序变慢了！
        // 锁只规定互斥访问，没有规定必须让谁优先执行
        // 锁就是真是的让多个执行流进行竞争的结果
        // pthread_mutex_lock(&lock);
        // pthread_mutex_lock(&lock);
        {
            // RAII风格的加锁！
            if (tickets > 0)
            {
                usleep(1254); // 1秒 = 1000毫秒 = 1000 000 微妙 = 10^9纳秒
                // 值得抢
                //  std::cout << td->threadname_ << " 正在进行抢票: "<< tickets << std::endl;
                std::cout << username << " 正在进行抢票: " << tickets << std::endl;
                // 用这段时间来模拟真实的抢票要花费的时间
                tickets--;
            }
            else
            {
                // pthread_mutex_unlock(&lock);
                break;
            }
        }
        // 抢完票就完了了吗？当然不是
        // usleep(1000); // 形成一个订单给用户
    }

    // other code

    return nullptr;
}

int main()
{
    std::unique_ptr<Thread> thread1(new Thread(getTicket, (void *)"user1", 1));
    std::unique_ptr<Thread> thread2(new Thread(getTicket, (void *)"user2", 2));
    std::unique_ptr<Thread> thread3(new Thread(getTicket, (void *)"user3", 3));
    std::unique_ptr<Thread> thread4(new Thread(getTicket, (void *)"user4", 4));

    thread1->join();
    thread2->join();
    thread3->join();
    thread4->join();

    return 0;
}